package com.wanqing.config;

import com.wanqing.interceptor.JwtTokenAdminInterceptor;
import com.wanqing.interceptor.JwtTokenUserInterceptor;
import com.wanqing.json.JacksonObjectMapper;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import java.util.List;

/**
 * 配置类，注册web层相关组件
 */
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {

    @Autowired
    private JwtTokenAdminInterceptor jwtTokenAdminInterceptor;
    @Autowired
    private JwtTokenUserInterceptor jwtTokenUserInterceptor;

    /**
     * 注册自定义拦截器
     *
     * @param registry
     */
    protected void addInterceptors(InterceptorRegistry registry) {
        log.info("开始注册自定义拦截器...");
        registry.addInterceptor(jwtTokenAdminInterceptor)
                .addPathPatterns("/admin/**")
                .excludePathPatterns("/admin/employee/login");

        registry.addInterceptor(jwtTokenUserInterceptor)
                .addPathPatterns("/user/**")
                .excludePathPatterns("/user/user/login")
                .excludePathPatterns("/user/user/login/getCode")
                .excludePathPatterns("/user/shop/status");
    }

    /**
     * 通过knife4j配置基本信息
     */
    @Bean
    public OpenAPI openAPI() {
        // 构建接口文档基本信息
        Info info = new Info()
                .title("智慧万青时光书屋项目接口文档")  // 文档标题
                .version("2.0")               // 文档版本
                .description("本项目是一个同城智慧书店平台，分为商家后台管理运营端和用户下单社区端。" +
                        " 商家端实现了营业报表、登录鉴权，员工和书籍、书单、优惠券、订单管理功能。" +
                        " 用户端可以浏览下单，读书分享，读书打卡，打卡排行榜，优惠券秒杀。 " +
                        "同时具有AI智能客服和智能助手，" +
                        "AI智能客服可以浏览资讯图书，可以图书推荐，可以下单等等；" +
                        " AI智能助手可以帮助商家快速了解订单情况和每天营业情况，以及在售图书库存量，智能库存预警等");  // 文档描述

        // 返回OpenAPI对象
        return new OpenAPI()
                .info(info);  // 设置文档基本信息
    }

    /**
     * 设置静态资源映射
     *
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // Knife4j 文档页面
        registry.addResourceHandler("/doc.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        // 通用 WebJars 资源（Knife4j 和 Swagger UI 都会用到）
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    /**
     * 扩展消息转换器列表
     * <p>
     * 该方法用于向Spring的HTTP消息转换器列表中添加自定义的消息转换器
     * 它允许我们定义如何在HTTP请求和响应中序列化和反序列化对象
     * 这个是导致knife4j不能正常显示的罪魁祸首,特别要注意添加的位置
     *
     * @param converters Spring的HTTP消息转换器列表，我们可以向其中添加自定义转换器
     */
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 记录日志，表示开始扩展消息转换器
        log.info("扩展消息转换器...");

        // 创建一个消息转换器
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();

        // 为消息转换器设置一个对象转换器，用于在Java对象和JSON数据之间进行转换
        converter.setObjectMapper(new JacksonObjectMapper());

        // 将自己的消息转换器加入到容器中
        converters.add(converters.size()-1, converter);
    }
}
